package gu.simplemq;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;

import com.google.common.collect.Maps;
import com.google.common.net.HostAndPort;

import gu.simplemq.pool.BaseMQPool;

import static com.google.common.base.Preconditions.*;

/**
 * {@link IMessageQueueFactory}实现基类
 * @author guyadong
 *
 */
@SuppressWarnings("rawtypes")
public abstract class BaseMessageQueueFactory<P extends BaseMQPool> implements IMessageQueueFactory {

	/**
	 * 原始的消息系统连接参数
	 */
	protected Map<String, Object> mqConnParams = Collections.emptyMap();
	private volatile HostAndPort hostAndPort;
	protected P pool;
	protected final IAdvisor advisor = new ZeroAdvisor();
	protected BaseMessageQueueFactory() {
	}

	/**
	 * 执行工厂类初始化
	 * @param properties
	 */
	protected abstract void doInit(Map<String, Object> properties);
	/**
	 * @return 返回消息系统服务器的主机名和端口
	 */
	protected abstract HostAndPort doGetHostAndPort() ;
	@SuppressWarnings("unchecked")
	protected P getPool() {
		return (P) checkInitialized().pool;
	}

	@Override
	public boolean initialized() {
		return pool != null;
	}

	@Override
	public BaseMessageQueueFactory init(Map<String, Object> properties) {
		// double check
		if(!initialized()){
			synchronized (this) {
				if(!initialized()){
					doInit(properties);
				}
			}
		}
		return this;
	}
	
	@Override
	public BaseMessageQueueFactory init(IMQConnParameterSupplier supplier) {
		return init(checkNotNull(supplier,"supplier is null").getMQConnParameters());
	}
	@Override
	public BaseMessageQueueFactory init(String json) {
		return init(MessageQueueFactorys.asMQConnParam(json));
	}

	@Override
	public BaseMessageQueueFactory checkInitialized(){
		checkState(initialized(),"current instance is uninitizlied");
		return this;
	}
	@Override
	public BaseMessageQueueFactory asDefaultFactory(){
		MessageQueueFactorys.setDefaultFactory(this);
		return this;
	}
	@Override
	public HostAndPort getHostAndPort() {
		// double check
		if(hostAndPort == null){
			synchronized(this){
				if(hostAndPort == null){
					hostAndPort = doGetHostAndPort();
				}
			}
		}
		return hostAndPort;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Map<String, Object> getMQConnParameters(){
		return Maps.newHashMap(checkInitialized().mqConnParams);
	}

	@Override
	public BaseMessageQueueFactory setAdvisor(IAdvisor advisor){
		return this;
	}
	public IAdvisor getAdvisor(){
		return advisor;
	}
	@Override
	public synchronized void close() throws IOException {
		if(pool != null){
			pool.close();
			pool = null;
		}
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append(getClass().getSimpleName() + " [implementation type=");
		builder.append(getImplType());
		builder.append(",mqConnParams=");
		builder.append(mqConnParams);
		builder.append("]");
		return builder.toString();
	}
}
